package sql.query;

import com.google.common.collect.Maps;
import sql.parser.SyntaxNode;
import sql.ast.Context;
import sql.ast.Node;
import sql.ast.State;

import java.util.List;
import java.util.Map;

public class ObjectUpdate {
    private final ObjectVisitor objectVisitor;
    private SyntaxNode updateSqlNode;

    public ObjectUpdate(ObjectVisitor objectVisitor, SyntaxNode updateSqlNode) {
        this.objectVisitor = objectVisitor;
        this.updateSqlNode = updateSqlNode;
    }

    public void update() {
        SyntaxNode fromNode = this.updateSqlNode.getFromNode();
        String table = fromNode.getTokenAsString();
        SyntaxNode updatePairs = this.updateSqlNode.getUpdateNode();
        SyntaxNode whereNode = this.updateSqlNode.getWhereNode();
        List list = objectVisitor.readTable(table);
        List<SyntaxNode> pairs = updatePairs.getChildren();
        Transformer transformer = new Transformer(this.objectVisitor);
        Node conditionNode = transformer.transformConditionNode(whereNode, table);

        int affected = 0;
        for (int i = 0; i < list.size(); i++) {
            Map map = (Map) list.get(i);
            Context context = new Context();
            context.setRow(map);
            State state = conditionNode.execute(context);
            if(state != State.True) {
                continue;
            }

            for (SyntaxNode pair : pairs) {
                List<SyntaxNode> items = pair.getChildren();
                SyntaxNode key = items.get(0);
                SyntaxNode value = items.get(2);

                if(value.getSelectNode() != null) {
                    ObjectQuery objectQuery = transformer.transformObjectQuery(value);
                    Map<String,Map> args0 = Maps.newHashMap();
                    args0.put(table, map);
                    String queryResult = objectQuery.execSingleString(args0);
                    map.put(key.getTokenAsString(), queryResult);
                } else {
                    map.put(key.getTokenAsString(), value.getTokenAsString());
                }
            }
            affected++;
        }
        objectVisitor.writeTable(table, list);
        System.out.println(affected + "行受影响");
    }
}
